import type { Router, RouteRecordRaw } from "vue-router";
import { cloneDeep } from "es-toolkit";
import Cookies from "js-cookie";
import { createRouter, createWebHistory } from "vue-router";
import { userStorage } from "@/config/storage";
import { multipleTabsKey, removeToken } from "@/utils/auth";
import NProgress from "@/utils/progress";
import { buildHierarchyTree } from "@/utils/tools";
import remainingRouter from "./modules/remaining";
import { changeBrowserTitle, formatFlatteningRoutes, formatTwoStageRoutes, getFirstMenuRoute, handleAliveRoute, routeRankAscending } from "./utils";

// TODO 单点登录

// #region----------------------------------------处理静态菜单------------------------------------

// 分为静态路由和动态路由两种, 静态路由在路由配置中直接定义, 动态路由则是通过后端 API 获取

/** 原始静态菜单路由（未做任何处理） */
export const originRoutes: RouteRecordRaw[] = [] satisfies RouteConfigsTable[];

/**
 * 自动导入全部静态路由，无需再手动引入！匹配 src/router/modules 目录（任何嵌套级别）中具有 .ts 扩展名的所有文件
 * 除了 remaining.ts 文件, remaining.ts 文件是一个特殊的路由模块，包含一些不参与菜单的路由
 * 如何匹配所有文件请看：https://github.com/mrmlnc/fast-glob#basic-syntax
 * 如何排除文件请看：https://cn.vitejs.dev/guide/features.html#negative-patterns
 */
const modules: Record<string, any> = import.meta.glob(
    ["./modules/**/*.ts", "!./modules/**/remaining.ts"],
    { eager: true }, // 同步导入
);

/* 将所有模块的默认导出合并到 routes 数组中 */
Object.keys(modules).forEach((key) => {
    originRoutes.push(modules[key].default);
});

/** 不参与菜单的路由路径 */
export const remainingPaths = remainingRouter.map(v => v.path);

// TODO 验证多级嵌套路由是否正确
/**
 * Note[router] keep-alive bug
 * 导出处理后的静态路由
 * 这里三级及以上的菜单路由全部拍成二级, 采用二级路由, 多级菜单的形式, 最后拼上非菜单路由(remainingRouter, 不拍成二级)
 * 因为 keep-alive 存在 bug, 二层 router-view 嵌套中 keep-alive 包的组件会二次创建, 参考:
 * https://github.com/vuejs/router/issues/626 (截止2025/10/16, 还没有修复)
 * https://github.com/vuejs/core/issues/12017
 * https://github.com/pure-admin/vue-pure-admin/issues/67
 */
// Note[js] flat返回一个新数组，参考 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/flat
// 首先将原始路由数组flat（并不是拍平）, 接着对顶层路由排序，然后构建层级关系（拍平后仍然可以查找父子关系）
// 进入拍平流程，将所有路由（包括子路由）构建一维数组，所有的子路由会放在父路由后面，不会打散；将一维数组重新处理二级路由格式
// 最后拼接上 remainingRouter（不拍成二级），形成最终的静态路由数组
export const constantRoutes: Array<RouteRecordRaw> = formatTwoStageRoutes(
    formatFlatteningRoutes(buildHierarchyTree(routeRankAscending(originRoutes.flat(Infinity)), "meta")),
).concat(...remainingRouter);

/** 用于渲染菜单，保持原始层级 */
export const constantMenus: Array<RouteRecordRaw> = routeRankAscending(
    originRoutes.flat(Infinity),
).concat(...remainingRouter);

/** 初始的静态路由，用于退出登录时重置路由 */
export const initConstantRoutes: Array<RouteRecordRaw> = cloneDeep(constantRoutes);

// #endregion-------------------------------------处理静态菜单------------------------------------

// #region----------------------------------------创建路由实例------------------------------------

// Note[router] strict https://router.vuejs.org/zh/guide/essentials/route-matching-syntax.html#Sensitive-%E4%B8%8E-strict-%E8%B7%AF%E7%94%B1%E9%85%8D%E7%BD%AE
// Note[router] scrollBehavior https://router.vuejs.org/zh/guide/advanced/scroll-behavior.html#%E6%BB%9A%E5%8A%A8%E8%A1%8C%E4%B8%BA
/** 创建路由实例 */
const router: Router = createRouter({
    history: createWebHistory(import.meta.env.BASE_URL),
    strict: true,
    scrollBehavior(to, from, savedPosition) {
        if (savedPosition) {
            return savedPosition;
        } else {
            return { left: 0, top: 0 };
        }
    },
    routes: constantRoutes,
});

// #endregion-------------------------------------创建路由实例------------------------------------

// #region----------------------------------------路由守卫----------------------------------------

/** 路由白名单 */
const whiteList = ["/login"];

/** 登录后不能访问的路由, 为路由白名单的子集 */
const loginNotList = ["/login"];

/** 是否隐藏首页 */
const { VITE_HIDE_HOME } = import.meta.env;

router.beforeEach(async (to: ToRouteType, from, next) => {
    NProgress.start();

    // TODO 路由缓存处理, 梳理这里的逻辑
    if (to.meta?.keepAlive) {
        handleAliveRoute(to, "add");
        // 页面整体刷新或点击标签页刷新
        if (from.name === undefined || from.name === "Redirect") {
            handleAliveRoute(to);
        }
    }
    const isExternalLink = to.meta?.menuType === "external"; // 是否是外链
    if (!isExternalLink) changeBrowserTitle(to);// 更新项目标题

    /** 如果已经登录并存在登录信息后, 则不能跳转到路由白名单，而是继续保持在当前页面 */
    function toCorrectRoute(): void {
        loginNotList.includes(to.fullPath) ? next(from.fullPath) : next();
    }

    const userInfo = userStorage.value;

    // 免登录时效内(未设置则默认浏览器退出前), 已登录的用户可以直接访问系统内的页面
    if (Cookies.get(multipleTabsKey) && userInfo) {
        // 开启隐藏首页后自动跳转到第一个菜单
        if (VITE_HIDE_HOME === "true" && to.fullPath === "/welcome") {
            const path = getFirstMenuRoute()?.path;
            next({ path, replace: true });
        }
        if (from?.name) {
            if (isExternalLink) { // to.name为超链接
                window.open(to?.name as string, "_blank");
                NProgress.done();
            } else {
                toCorrectRoute();
            }
        } else {
            toCorrectRoute();
        }
    } else { // 未登录
        if (to.path !== "/login") {
            if (whiteList.includes(to.path)) {
                next();
            } else {
                removeToken(false);
                next({ path: "/login" });
            }
        } else {
            next();
        }
    }
});

router.afterEach(() => {
    NProgress.done();
});

// #endregion-------------------------------------路由守卫--------------------------------------

export default router;
